﻿
using System;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace NFinal.Common.Plugin
{
    /// <summary>
    /// 插件封装类
    /// </summary>
    /// <typeparam name="TService">插件执行类的接口或父类</typeparam>
    public class PluginWrapper<TService> where TService : class
    {
        /// <summary>
        /// 插件信息
        /// </summary>
        public PluginInfo PluginInfo { get; set; }
        private static object _lock = new object();
        /// <summary>
        /// 插件初始化(安装)
        /// </summary>
        /// <param name="pluginInfo">插件信息</param>
        public PluginWrapper(PluginInfo pluginInfo
#if UNLOAD
            ,out WeakReference weakReference
#endif
            )
        {
            PluginInfo = pluginInfo;
            PluginManager.InstallPlug(pluginInfo.Name, pluginInfo.PluginFolder,//typeof(TService).Assembly.GetName(),
#if UNLOAD
            out weakReference, 
#endif
            new string[] { pluginInfo.CommonAssemblyFolder});
        }

        
        /// <summary>
        /// 创建对象,对象内置
        /// </summary>
        public TService New()
        {
             return PluginManager.CreateInstance<TService>(PluginInfo.Name, PluginInfo.AssemblyName, PluginInfo.ClassName );
        }

        /// <summary>
        /// 执行同步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        public void Execute(string methodName )
        {
            PluginManager.ExecuteMethod<TService>(PluginInfo.Name,PluginInfo.ClassName, methodName );
        }

        /// <summary>
        /// 执行异步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        public Task ExecuteAsync(string methodName )
        {
            return PluginManager.ExecuteMethodAsync<TService>(PluginInfo.Name,PluginInfo.ClassName, methodName );
        }
        
        /// <summary>
        /// 创建对象,对象内置
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        public TService New< T1>( T1 t1)
        {
             return PluginManager.CreateInstance<TService, T1>(PluginInfo.Name, PluginInfo.AssemblyName, PluginInfo.ClassName , t1);
        }

        /// <summary>
        /// 执行同步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        public void Execute< T1>(string methodName , T1 t1)
        {
            PluginManager.ExecuteMethod<TService, T1>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1);
        }

        /// <summary>
        /// 执行异步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        public Task ExecuteAsync< T1>(string methodName , T1 t1)
        {
            return PluginManager.ExecuteMethodAsync<TService, T1>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1);
        }
        
        /// <summary>
        /// 创建对象,对象内置
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        public TService New< T1, T2>( T1 t1, T2 t2)
        {
             return PluginManager.CreateInstance<TService, T1, T2>(PluginInfo.Name, PluginInfo.AssemblyName, PluginInfo.ClassName , t1, t2);
        }

        /// <summary>
        /// 执行同步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        public void Execute< T1, T2>(string methodName , T1 t1, T2 t2)
        {
            PluginManager.ExecuteMethod<TService, T1, T2>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2);
        }

        /// <summary>
        /// 执行异步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        public Task ExecuteAsync< T1, T2>(string methodName , T1 t1, T2 t2)
        {
            return PluginManager.ExecuteMethodAsync<TService, T1, T2>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2);
        }
        
        /// <summary>
        /// 创建对象,对象内置
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        public TService New< T1, T2, T3>( T1 t1, T2 t2, T3 t3)
        {
             return PluginManager.CreateInstance<TService, T1, T2, T3>(PluginInfo.Name, PluginInfo.AssemblyName, PluginInfo.ClassName , t1, t2, t3);
        }

        /// <summary>
        /// 执行同步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        public void Execute< T1, T2, T3>(string methodName , T1 t1, T2 t2, T3 t3)
        {
            PluginManager.ExecuteMethod<TService, T1, T2, T3>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3);
        }

        /// <summary>
        /// 执行异步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        public Task ExecuteAsync< T1, T2, T3>(string methodName , T1 t1, T2 t2, T3 t3)
        {
            return PluginManager.ExecuteMethodAsync<TService, T1, T2, T3>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3);
        }
        
        /// <summary>
        /// 创建对象,对象内置
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        public TService New< T1, T2, T3, T4>( T1 t1, T2 t2, T3 t3, T4 t4)
        {
             return PluginManager.CreateInstance<TService, T1, T2, T3, T4>(PluginInfo.Name, PluginInfo.AssemblyName, PluginInfo.ClassName , t1, t2, t3, t4);
        }

        /// <summary>
        /// 执行同步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        public void Execute< T1, T2, T3, T4>(string methodName , T1 t1, T2 t2, T3 t3, T4 t4)
        {
            PluginManager.ExecuteMethod<TService, T1, T2, T3, T4>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3, t4);
        }

        /// <summary>
        /// 执行异步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        public Task ExecuteAsync< T1, T2, T3, T4>(string methodName , T1 t1, T2 t2, T3 t3, T4 t4)
        {
            return PluginManager.ExecuteMethodAsync<TService, T1, T2, T3, T4>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3, t4);
        }
        
        /// <summary>
        /// 创建对象,对象内置
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        public TService New< T1, T2, T3, T4, T5>( T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
        {
             return PluginManager.CreateInstance<TService, T1, T2, T3, T4, T5>(PluginInfo.Name, PluginInfo.AssemblyName, PluginInfo.ClassName , t1, t2, t3, t4, t5);
        }

        /// <summary>
        /// 执行同步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        public void Execute< T1, T2, T3, T4, T5>(string methodName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
        {
            PluginManager.ExecuteMethod<TService, T1, T2, T3, T4, T5>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3, t4, t5);
        }

        /// <summary>
        /// 执行异步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        public Task ExecuteAsync< T1, T2, T3, T4, T5>(string methodName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
        {
            return PluginManager.ExecuteMethodAsync<TService, T1, T2, T3, T4, T5>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3, t4, t5);
        }
        
        /// <summary>
        /// 创建对象,对象内置
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="t6">参数6</param>
        public TService New< T1, T2, T3, T4, T5, T6>( T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
        {
             return PluginManager.CreateInstance<TService, T1, T2, T3, T4, T5, T6>(PluginInfo.Name, PluginInfo.AssemblyName, PluginInfo.ClassName , t1, t2, t3, t4, t5, t6);
        }

        /// <summary>
        /// 执行同步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="t6">参数6</param>
        public void Execute< T1, T2, T3, T4, T5, T6>(string methodName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
        {
            PluginManager.ExecuteMethod<TService, T1, T2, T3, T4, T5, T6>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3, t4, t5, t6);
        }

        /// <summary>
        /// 执行异步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="t6">参数6</param>
        public Task ExecuteAsync< T1, T2, T3, T4, T5, T6>(string methodName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
        {
            return PluginManager.ExecuteMethodAsync<TService, T1, T2, T3, T4, T5, T6>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3, t4, t5, t6);
        }
        
        /// <summary>
        /// 创建对象,对象内置
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="t6">参数6</param>
        /// <typeparam name="T7">参数7类型</typeparam>
        /// <param name="t7">参数7</param>
        public TService New< T1, T2, T3, T4, T5, T6, T7>( T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
        {
             return PluginManager.CreateInstance<TService, T1, T2, T3, T4, T5, T6, T7>(PluginInfo.Name, PluginInfo.AssemblyName, PluginInfo.ClassName , t1, t2, t3, t4, t5, t6, t7);
        }

        /// <summary>
        /// 执行同步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="t6">参数6</param>
        /// <typeparam name="T7">参数7类型</typeparam>
        /// <param name="t7">参数7</param>
        public void Execute< T1, T2, T3, T4, T5, T6, T7>(string methodName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
        {
            PluginManager.ExecuteMethod<TService, T1, T2, T3, T4, T5, T6, T7>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3, t4, t5, t6, t7);
        }

        /// <summary>
        /// 执行异步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="t6">参数6</param>
        /// <typeparam name="T7">参数7类型</typeparam>
        /// <param name="t7">参数7</param>
        public Task ExecuteAsync< T1, T2, T3, T4, T5, T6, T7>(string methodName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
        {
            return PluginManager.ExecuteMethodAsync<TService, T1, T2, T3, T4, T5, T6, T7>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3, t4, t5, t6, t7);
        }
        
        /// <summary>
        /// 创建对象,对象内置
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="t6">参数6</param>
        /// <typeparam name="T7">参数7类型</typeparam>
        /// <param name="t7">参数7</param>
        /// <typeparam name="T8">参数8类型</typeparam>
        /// <param name="t8">参数8</param>
        public TService New< T1, T2, T3, T4, T5, T6, T7, T8>( T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
        {
             return PluginManager.CreateInstance<TService, T1, T2, T3, T4, T5, T6, T7, T8>(PluginInfo.Name, PluginInfo.AssemblyName, PluginInfo.ClassName , t1, t2, t3, t4, t5, t6, t7, t8);
        }

        /// <summary>
        /// 执行同步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="t6">参数6</param>
        /// <typeparam name="T7">参数7类型</typeparam>
        /// <param name="t7">参数7</param>
        /// <typeparam name="T8">参数8类型</typeparam>
        /// <param name="t8">参数8</param>
        public void Execute< T1, T2, T3, T4, T5, T6, T7, T8>(string methodName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
        {
            PluginManager.ExecuteMethod<TService, T1, T2, T3, T4, T5, T6, T7, T8>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3, t4, t5, t6, t7, t8);
        }

        /// <summary>
        /// 执行异步方法
        /// </summary>
        /// <param name="methodName">方法名</param>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="t2">参数2</param>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="t3">参数3</param>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="t4">参数4</param>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="t5">参数5</param>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="t6">参数6</param>
        /// <typeparam name="T7">参数7类型</typeparam>
        /// <param name="t7">参数7</param>
        /// <typeparam name="T8">参数8类型</typeparam>
        /// <param name="t8">参数8</param>
        public Task ExecuteAsync< T1, T2, T3, T4, T5, T6, T7, T8>(string methodName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
        {
            return PluginManager.ExecuteMethodAsync<TService, T1, T2, T3, T4, T5, T6, T7, T8>(PluginInfo.Name,PluginInfo.ClassName, methodName , t1, t2, t3, t4, t5, t6, t7, t8);
        }
        
        public void UnInstall()
        {
            PluginManager.UnInstall(PluginInfo.Name);
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    public class PluginWrapper :PluginWrapper<object>
    {
            public PluginWrapper(
#if UNLOAD
            PluginInfo pluginInfo,out WeakReference weakReference):base(pluginInfo,out weakReference)
#else
            PluginInfo pluginInfo):base(pluginInfo)
#endif
        {

        }
    }
}
